/*
 * shared_rt_record.hpp
 *
 *  Created on: 2023年9月7日
 *      Author: Dylan.Gao
 */

#ifndef _DM_OS_SHARED_RT_RECORD_HPP_
#define _DM_OS_SHARED_RT_RECORD_HPP_

#include <dm/timestamp.hpp>
#include <dm/runtimestamp.hpp>
#include <dm/os/types.hpp>

namespace dm{
namespace os{

/**
 * 共享的实时记录
 * @tparam TInfo 记录信息类型
 * @tparam TValue 记录数值类型
 */
template<typename TInfo,typename TValue,typename TId=dm::int64>
struct TSSharedRtRecord{
	typedef upgradable_mutex_t mutex_t;

	/**
	 * 加载器类
	 * 实现将信息加载到记录中去
	 */
	class CLoader{
	public:
		virtual ~CLoader(){}

		/**
		 * 加载记录信息
		 * @param i 需要更新的记录信息
		 * @param v 需要更新的记录值
		 * @param ts 需要更新的记录时标
		 * @param rts 需要更新的记录运行时标
		 * @param tsNow 当前时标
		 * @param rtsNow 当前运行时标
		 * @return 是否更新成功
		 */
		virtual bool loadRecord( TInfo& i,TValue& v,CTimeStamp& ts,CRunTimeStamp& rts,const CTimeStamp& tsNow,const CRunTimeStamp& rtsNow )=0;
	};

	/**
	 * 普通加载器类
	 * 提供一般类型的加载器
	 */
	class CNormalLoader:public CLoader{
	public:
		CNormalLoader( TInfo* pInfo=nullptr,TValue* pValue=nullptr ):m_pInfo(pInfo),m_pValue(pValue){}

		inline void setInfo( TInfo* pInfo ){
			m_pInfo = pInfo;
		}

		inline void setValue( TValue* pValue ){
			m_pValue = pValue;
		}

		bool loadRecord( TInfo& i,TValue& v,CTimeStamp& ts,CRunTimeStamp& rts,const CTimeStamp& tsNow,const CRunTimeStamp& rtsNow ){
			if( m_pInfo )
				memcpy(&i,m_pInfo,sizeof(TInfo));
			if( m_pValue )
				memcpy(&v,m_pValue,sizeof(TValue));

			ts = tsNow;
			rts = rtsNow;

			return true;
		}
	protected:
		TInfo* m_pInfo;
		TValue* m_pValue;
	};

	/**
	 * 比较器类
	 */
	class CComparer{
	public:
		virtual ~CComparer(){}

		virtual bool compareById( const TInfo& i,const TId& id ){
			return false;
		}

		virtual bool compareByName( const TInfo& i,const char* name ){
			return false;
		}

		virtual bool compareByAny( const TInfo& i,void* key ){
			return false;
		}
	};

	/**
	 * ID比较器类
	 */
	class CIdComparer:public CComparer{
	public:
		bool compareById( const TInfo& i,const TId& id ){
			return i.id==id;
		}
	};

	/**
	 * 名字比较器类
	 */
	class CNameComparer:public CComparer{
	public:
		bool compareByName( const TInfo& i,const char* name ){
			return i.name==name;
		}
	};

	/**
	 * 任意信息比较器类
	 */
	class CAnyComparer:public CComparer{
	public:
		bool compareByAny( const TInfo& i,void* key ){
			TInfo* pInfo = reinterpret_cast<TInfo*>(key);
			if( !pInfo )
				return false;

			return memcmp(&i,pInfo,sizeof(TInfo))==0;
		}
	};

	/**
	 * 一般比较器类
	 */
	class CNormalComparer:public CComparer{
	public:
		bool compareById( const TInfo& i,const TId& id ){
			return i.id==id;
		}

		bool compareByName( const TInfo& i,const char* name ){
			return i.name==name;
		}

		bool compareByAny( const TInfo& i,void* key ){
			TInfo* pInfo = reinterpret_cast<TInfo*>(key);
			if( !pInfo )
				return false;

			return memcmp(&i,pInfo,sizeof(TInfo))==0;
		}
	};

	/**
	 * 读取器类
	 * 从记录中读取需要的信息
	 */
	class CReader{
	public:
		virtual ~CReader(){}

		virtual bool readRecord( TInfo& i,TValue& v,CTimeStamp& ts,CRunTimeStamp& rts,TInfo* pInfo=nullptr,TValue* pValue=nullptr,CTimeStamp* pTs=nullptr,CRunTimeStamp* pRts=nullptr,void* temp=nullptr )=0;
	};

	/**
	 * 一般读取器类
	 */
	class CNormalReader:public CReader{
	public:
		/**
		 * 实现一般的记录读取功能。分别将记录中的信息，状态，和时标都拷贝出来
		 * @param i
		 * @param v
		 * @param ts
		 * @param rts
		 * @param pInfo
		 * @param pValue
		 * @param pTs
		 * @param pRts
		 * @param temp 未使用
		 * @return
		 */
		virtual bool readRecord( TInfo& i,TValue& v,CTimeStamp& ts,CRunTimeStamp& rts,TInfo* pInfo=nullptr,TValue* pValue=nullptr,CTimeStamp* pTs=nullptr,CRunTimeStamp* pRts=nullptr,void* temp=nullptr ){
			if( pInfo )
				memcpy(pInfo,&i,sizeof(TInfo));
			if( pValue )
				memcpy(pValue,&v,sizeof(TValue));
			if( pTs )
				*pTs = ts;
			if( pRts )
				*pRts = rts;

			return true;
		}
	};

	/**
	 * ID读取器
	 */
	class CIdReader:public CReader{
	public:
		bool readRecord( TInfo& i,TValue& v,CTimeStamp& ts,CRunTimeStamp& rts,TInfo* pInfo=nullptr,TValue* pValue=nullptr,CTimeStamp* pTs=nullptr,CRunTimeStamp* pRts=nullptr,void* temp=nullptr ){
			TId* pId = reinterpret_cast<TId*>(temp);
			if( !pId )	// id需要通过temp获取
				return false;

			*pId = i.id;

			return true;
		}
	};

	/**
	 * 数值更新器
	 */
	class CValueUpdater{
	public:
		virtual ~CValueUpdater(){};

		/**
		 * 测试记录是否发生变化
		 * @param i 记录中的配置信息
		 * @param v 记录中的值信息
		 * @param ts 记录中的时标信息
		 * @param rts 记录中的运行时标信息
		 * @param temp 新的内容
		 * @param tsNow 当前时标
		 * @param rtsNow 当前运行时标
		 * @return
		 */
		virtual bool isValueChanged( TInfo& i,TValue& v,CTimeStamp& ts,CRunTimeStamp& rts,void* temp,const CTimeStamp& tsNow,const CRunTimeStamp& rtsNow )=0;

		/**
		 * 更新记录
		 * @param i 记录中的配置信息
		 * @param v 记录中的值信息
		 * @param ts 记录中的时标信息
		 * @param rts 记录中的运行时标信息
		 * @param temp 新的内容
		 * @param tsNow 当前时标
		 * @param rtsNow 当前运行时标
		 * @return
		 */
		virtual bool updateValue( TInfo& i,TValue& v,CTimeStamp& ts,CRunTimeStamp& rts,void* temp,const CTimeStamp& tsNow,const CRunTimeStamp& rtsNow )=0;
	};

	/**
	 * 一般数值更新器
	 */
	class CNormalValueUpdater:public CValueUpdater{
		/**
		 * 比较记录中的值是否发生变化
		 * @param i
		 * @param v
		 * @param ts
		 * @param rts
		 * @param temp
		 * @param tsNow
		 * @param rtsNow
		 * @return
		 */
		bool isValueChanged( TInfo& i,TValue& v,CTimeStamp& ts,CRunTimeStamp& rts,void* temp,const CTimeStamp& tsNow,const CRunTimeStamp& rtsNow ){
			TValue* pValue = reinterpret_cast<TValue*>(temp);
			if( !pValue )
				return false;

			return memcmp(pValue,&v,sizeof(TValue))!=0;
		}

		/**
		 * 更新记录
		 * @param i
		 * @param v
		 * @param ts
		 * @param temp
		 * @param now
		 * @return
		 */
		bool updateValue( TInfo& i,TValue& v,CTimeStamp& ts,CRunTimeStamp& rts,void* temp,const CTimeStamp& tsNow,const CRunTimeStamp& rtsNow ){
			TValue* pValue = reinterpret_cast<TValue*>(temp);
			if( !pValue )
				return false;

			memcpy(&v,pValue,sizeof(TValue));
			ts = tsNow;
			rts = rtsNow;

			return true;
		}
	};

	/**
	 * 值设置器类
	 */
	class CValueWriter{
	public:
		virtual ~CValueWriter(){}

		virtual bool writeValue( TInfo& i,TValue& v,CTimeStamp& ts,CRunTimeStamp& rts,void* temp,const CTimeStamp& tsNow,const CRunTimeStamp& rtsNow )=0;
	};

	class CNormalValueWriter:public CValueWriter{
	public:
		bool writeValue( TInfo& i,TValue& v,CTimeStamp& ts,CRunTimeStamp& rts,void* temp,const CTimeStamp& tsNow,const CRunTimeStamp& rtsNow ){
			TValue* pValue = reinterpret_cast<TValue*>(temp);
			if( !pValue )
				return false;

			memcpy(&v,pValue,sizeof(TValue));
			ts = tsNow;
			rts = rtsNow;

			return true;
		}
	};

	mutex_t mutex;		// 记录互斥量
	TInfo info;			// 记录信息
	TValue value;		// 记录数据
	CTimeStamp timeStamp;		// 悬挂时标
	CRunTimeStamp rtimeStamp;	// 计数时标

	/**
	 * 强制初始化记录
	 */
	bool reload( CLoader& loader,const CTimeStamp& tsNow=CTimeStamp::cur(),const CRunTimeStamp& rtsNow=CRunTimeStamp::cur() ){
		boost::interprocess::scoped_lock<mutex_t> scopedLock(mutex);
		try{
			return loader.loadRecord(info, value, timeStamp,rtimeStamp,tsNow,rtsNow);
		}catch(...){
			return false;
		}

	}

	/**
	 * 获取记录
	 * 读锁定
	 * @param temp 数据存放
	 * @param reader 读取器
	 * @param i 默认信息存储
	 * @param value 默认值存储
	 * @param ts 时标存储
	 * @param rts 运行失败存储
	 */
	bool get( void* temp,CReader& reader,TInfo* i=nullptr,TValue* v=nullptr,CTimeStamp* ts=nullptr,CRunTimeStamp* rts=nullptr ){
		boost::interprocess::sharable_lock<mutex_t> sharableLock(mutex);
		try{
			return reader.readRecord(info, value, timeStamp,rtimeStamp, i, v, ts,rts, temp);
		}catch(...){
			return false;
		}

	}

	/**
	 * 根据ID进行比较
	 * @param id
	 * @param comparer
	 * @param temp
	 * @param reader
	 * @param i
	 * @param v
	 * @param ts
	 * @return
	 */
	bool compareById( const TId& id,CComparer& comparer,void* temp=nullptr,CReader* reader=nullptr,TInfo* i=nullptr,TValue* v=nullptr,CTimeStamp* ts=nullptr,CRunTimeStamp* rts=nullptr ){
		boost::interprocess::sharable_lock<mutex_t> sharableLock(mutex);
		try{
			if( comparer.compareById(info, id) ){
				if( temp && reader ){
					if( !reader->readRecord(info, value, timeStamp,rtimeStamp, i, v, ts,rts, temp) )
						return false;
				}

				return true;
			}
			return false;
		}catch(...){
			return false;
		}
	}

	bool compareByName( const char* name,CComparer& comparer,void* temp=nullptr,CReader* reader=nullptr,TInfo* i=nullptr,TValue* v=nullptr,CTimeStamp* ts=nullptr,CRunTimeStamp* rts=nullptr ){
		boost::interprocess::sharable_lock<mutex_t> sharableLock(mutex);
		try{
			if( comparer.compareByName(info, name) ){
				if( temp && reader ){
					if( !reader->readRecord(info, value, timeStamp,rtimeStamp, i, v, ts,rts, temp) )
						return false;
				}

				return true;
			}
			return false;
		}catch(...){
			return false;
		}
	}

	bool compareByAny( const void* key,CComparer& comparer,void* temp=nullptr,CReader* reader=nullptr,TInfo* i=nullptr,TValue* v=nullptr,CTimeStamp* ts=nullptr,CRunTimeStamp* rts=nullptr ){
		boost::interprocess::sharable_lock<mutex_t> sharableLock(mutex);
		try{
			if( comparer.compareByAny(info, key) ){
				if( temp && reader ){
					if( !reader->readRecord(info, value, timeStamp,rtimeStamp, i, v, ts,rts, temp) )
						return false;
				}

				return true;
			}
			return false;
		}catch(...){
			return false;
		}
	}

	/**
	 * 更新记录
	 * 先读锁定，判断是否一致
	 * 不一致时，升级锁，更新记录
	 * @param value
	 * @param ts
	 * @return 是否更新
	 */
	bool updateValue( void* temp,CValueUpdater& valueUpdater,const CTimeStamp& tsNow=CTimeStamp::cur(),const CRunTimeStamp& rtsNow=CRunTimeStamp::cur() ){
		boost::interprocess::upgradable_lock<mutex_t> upgradableLock(mutex);
		try{
			if( valueUpdater.isValueChanged(info, value, timeStamp,rtimeStamp, temp, tsNow,rtsNow) ){
				boost::interprocess::scoped_lock<mutex_t> scopedLock(boost::move(upgradableLock));
				return valueUpdater.updateValue(info, value, timeStamp,rtimeStamp, temp, tsNow,rtsNow );
			}

			return false;
		}catch(...){
			return false;
		}
	}

	/**
	 * 设置记录
	 * @param temp
	 * @param valueWriter
	 * @param tsNow
	 * @param rtsNow
	 * @return
	 */
	bool writeValue( void* temp,CValueWriter& valueWriter,const CTimeStamp& tsNow=CTimeStamp::cur(),const CRunTimeStamp& rtsNow=CRunTimeStamp::cur() ){
		boost::interprocess::scoped_lock<mutex_t> scopedLock(mutex);
		try{
			return valueWriter.writeValue(info, value, timeStamp, rtimeStamp, temp, tsNow, rtsNow);
		}catch(...){
			return false;
		}
	}
};

}
}



#endif /* _DM_OS_SHARED_RT_RECORD_HPP_ */
